package com.tuling.config;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.tuling.component.TulingTokenEnhancer;
import com.tuling.properties.JwtCAProperties;
import com.tuling.tulingmall.service.TulingUserDetailService;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
// import sun.misc.BASE64Decoder; //jdk11 找不到包了

import javax.sql.DataSource;
import java.nio.charset.Charset;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;

/**
* @vlog: 高于生活，源于生活
* @desc: 类的描述:认证服务器配置
* @author: smlz
* @createDate: 2020/1/21 21:48
* @version: 1.0
*/
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(value = JwtCAProperties.class)
public class TulingAuthServerConfig extends AuthorizationServerConfigurerAdapter {


    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private TulingUserDetailService tulingUserDetailService;

    @Autowired
    private JwtCAProperties jwtCAProperties;

    private String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkC0ZA7rr7IheH6QvSWxm2+w20BCflhiTx/93QN80dzaqsu59PIkEcO1bjvM8g2ukvur5zUhEUZ9PfCe7QTKPiFwVBRsIGWJ2BE2yBd9i7oszXSzRx4AlapgtFM5kif8W5hUKcAEVAN/a+BX9qPmujQeXN4w3spdTcXN9mTisEgC9CH1KhCTEuK4oYUDyzdY6wV4xc6DwKZpUmGPtXHSoVlUB//vuA1JOLQCSG+0f9upr/IZL/OKYQ3IVyddNHJUHaD+/cOb743O0oglur8fLQKh6jUKvt+WU0UfFdEG0YTgyB43slfqUVAZU0M1liYckQ+TCK8OMEab1KvWU3xuhtwIDAQAB";
            //"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCegevuObLr9H0czDGkI/bS/sNliNbbJmjxNS8aHEhBGs5NcfJX0CYMvXaXEmVugubczJmLqK3FFygocAdXJMB5JERqOSRwrzPWpFy4Lk0uPDCY+hjEBYYqx7Y8fDGZWtIdISFX2NTXZkmZAwxJ6gxxHlpuvdcrIwOcaRJAx1BedwIDAQAB";

    private String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQLRkDuuvsiF4fpC9JbGbb7DbQEJ+WGJPH/3dA3zR3Nqqy7n08iQRw7VuO8zyDa6S+6vnNSERRn098J7tBMo+IXBUFGwgZYnYETbIF32LuizNdLNHHgCVqmC0UzmSJ/xbmFQpwARUA39r4Ff2o+a6NB5c3jDeyl1Nxc32ZOKwSAL0IfUqEJMS4rihhQPLN1jrBXjFzoPApmlSYY+1cdKhWVQH/++4DUk4tAJIb7R/26mv8hkv84phDchXJ100clQdoP79w5vvjc7SiCW6vx8tAqHqNQq+35ZTRR8V0QbRhODIHjeyV+pRUBlTQzWWJhyRD5MIrw4wRpvUq9ZTfG6G3AgMBAAECggEAFi1puKIrIkJDwDhAMdoj5FZshArakXsMWGpajLcI2gGltkprJ0GoVjqcp9uQhmKrf9ajQEmKgMexsVZnPnspiv8nGJb04vq7TqQo6zBWhn0RFJcNWdPDback4Btzaaq8ef3okhwIgA7vHtQ7JZ/qkrUFNL0z4BvY8Q2j10rZZRdO3+lq89cNuXPIyoTaO4TP7Ft784+DqxcJC7lcBHOfaiVKRbWvSz1C+fOI0XidEEna6Oeyx2XP/1iTLd9h+Sp5UuBNrJ3Icu71ejh3Zx2a6VtMSr75wZAetMSdQfrYO3uRRJAutKCj36Ztz1YfQ5HWPN75oco15vegPC5Jfq6uAQKBgQDDOo+9pTElcxSGoYiAy/6Rw8Y6gXpJy3xWGGLn1XUkcE9FwSbqRHJUSIPYMuMUq2wVBggQc7nteqNlFqM7maUqgPGrwl0EEHY/0MsmZDHMX1+lgySbnAq8EV1CLI6LkMNj6VFUE/IhYFUMAX0pJZDlnNbXysVAFKaI3c6C94vetwKBgQC9Dj6JQiRDaGcdytos390b0cCwcz5pwvCpb2lFk5pSgzH8q7lVsejiUjp6cyXc2egnGcaWxmuYsxsqH8zyL7VeDNJkg49mmfGwNcfg2Xa1is/C1Kfa9Tu4GG63BMICfGf8w55OYwSNDMY/mP8pesNvhMRCYElLRdGxQHe0gUtVAQKBgQCHhP5EwggEnAbyke0EoxaartDKyhhOY49y4Ei/77/6RG/y1uqhklPex9ul12Ukcv569Y3hhcPZ4tjLklRLShOKFqor9abF7Ht5PwHWK5UZ7lahuRBPaJlXBaK8DdwBa8MGdu66s4HPw2QmCl6MkoQrr5y/fQVBv1P/DCGPbjFMrwKBgECodH7hHiHnvQyVahTa43Y2QJ6Ya4okX8azEd/34VnDAP+Xg6VpWWq+EL38T8C+zgVBbYf3iKkK6Il5otBZvL/TxskVrZ+7mstXOWsPNOhV90R9EoNyR+BoisURXYEYJ0BtbuEEQHQ1IEB0BSCcmea0E6NX5vlVgagLkmUrqyYBAoGASpjIfL5IdA/ftKeRzNyC/WL3zcVACle6gOsuBh4llN50VAPTkEh3TPu5TFyEcWFmhLX/LGHRWYcmuW9hsxE4uXGtM2K5GGsBSkd5Dz6Z48Oe5x+dIsIhXvYiqaSVaRZMN03/HhvpS5kc96eZBaMoBtAg1dPmnWYsgt/DH/uIVRc=";
            // "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ6B6+45suv0fRzMMaQj9tL+w2WI1tsmaPE1LxocSEEazk1x8lfQJgy9dpcSZW6C5tzMmYuorcUXKChwB1ckwHkkRGo5JHCvM9akXLguTS48MJj6GMQFhirHtjx8MZla0h0hIVfY1NdmSZkDDEnqDHEeWm691ysjA5xpEkDHUF53AgMBAAECgYAJseek2AmeDgOzBbhJkluP9z4rUS3XFKfZjQe3AKDYvpN8wCny/gu9vr7oqZrjogUN30PK+4O5aNuvcX65cUmGZq7d2eUxqtHr204GXM+s6orkGMm20mgBUt2xMdXeW6D3fLUP5EO9SzlOfwPjzc3va9qF/NkdUaYJFic58RXpRQJBAM95DFYJlnQBZUL/fD37fRc+sZtSYI2C2EAU7oG6emO5Oe9rXObZUKajemIWbQ7c2ZmlcOITUXsh3WH6zPIDvNsCQQDDlPPCh/4XE31GzeFLOj0/pwvC7R1/bqnfWMA61iN/8Any3YGEs82Tk305H9VGn07atCvprlE5kMh/3vVcq0mVAkBepJGEDgucD6bp0TIT9E0z9V1/xSxWYYHUebfzZeW+6BgNp6RRioDIA3sok6JcTVLWTCoad0WMLf6XW5lyLVJRAkAasczng0pB+g4CSP10GBneAz3OuDBrgT48Vs+9+BZWUvv4oxUXeLcZamsQDfE9N2c64JaRyZIailFjapoQsOxVAkBZls+vqe7+KBoGHH8SxSphWaWPoQkHMnhfCCE4PE/fdUp0f68UBHP8TB95a/CL62Otwg/sjQC0WFK/8nez/5JR";


    /**
     * 方法实现说明:我们颁发的token通过jwt存储
     * @author:smlz
     * @return:
     * @exception:
     * @date:2020/1/21 21:49
     */
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //jwt的密钥
        converter.setKeyPair(keyPair());
        return converter;
    }

    @Bean
    public KeyPair keyPair() {

//        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(jwtCAProperties.getKeyPairName()), jwtCAProperties.getKeyPairSecret().toCharArray());
//        return keyStoreKeyFactory.getKeyPair(jwtCAProperties.getKeyPairAlias(), jwtCAProperties.getKeyPairStoreSecret().toCharArray());
        PublicKey publicKey = SecureUtil.generatePublicKey("RSA", Base64.decode(PUBLIC_KEY));
        PrivateKey privateKey = SecureUtil.generatePrivateKey("RSA", Base64.decode(PRIVATE_KEY));
        return new KeyPair(publicKey, privateKey);
    }


    @Bean
    public TulingTokenEnhancer tulingTokenEnhancer() {
        return new TulingTokenEnhancer();
    }



    /**
     * 方法实现说明:认证服务器能够给哪些 客户端颁发token  我们需要把客户端的配置 存储到
     * 数据库中 可以基于内存存储和db存储
     * @author:smlz
     * @return:
     * @exception:
     * @date:2020/1/15 20:18
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());
    }

    /**
     * 方法实现说明:用于查找我们第三方客户端的组件 主要用于查找 数据库表 oauth_client_details
     * @author:smlz
     * @return:
     * @exception:
     * @date:2020/1/15 20:19
     */
    @Bean
    public ClientDetailsService clientDetails() {
        ClientDetailsService clientDetailsService =  new JdbcClientDetailsService(dataSource);

        return clientDetailsService;
    }

    /**
     * 方法实现说明:授权服务器的配置的配置
     * @author:smlz
     * @return:
     * @exception:
     * @date:2020/1/15 20:21
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tulingTokenEnhancer(),jwtAccessTokenConverter()));

        endpoints.tokenStore(tokenStore()) //授权服务器颁发的token 怎么存储的
                .tokenEnhancer(tokenEnhancerChain)
                .userDetailsService(tulingUserDetailService) //用户来获取token的时候需要 进行账号密码
                .authenticationManager(authenticationManager)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
    }


    /**
     * 方法实现说明:授权服务器安全配置
     * @author:smlz
     * @return:
     * @exception:
     * @date:2020/1/15 20:23
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 第三方客户端校验token需要带入 clientId 和clientSecret来校验
        security .checkTokenAccess("isAuthenticated()")
                 .tokenKeyAccess("isAuthenticated()")

        ;//来获取我们的tokenKey需要带入clientId,clientSecret

        security.allowFormAuthenticationForClients();
    }


    public static void main(String[] args) throws Exception{
//        RSA rsa = SecureUtil.rsa();
//        PrivateKey privateKey = rsa.getPrivateKey();
//
//        PublicKey publicKey = rsa.getPublicKey();
//




//        String text1 = "RAS测试、公钥加密 私钥解密";
//        RSA rsa = SecureUtil.rsa();
//        // 公钥加密
//        byte[] encrypt = rsa.encrypt(StrUtil.bytes(text1, CharsetUtil.UTF_8), KeyType.PublicKey);
//
//        // 私钥解密
//        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
//
//        String str = new String(decrypt, "UTF-8");
//
//        System.out.println("公钥加密、私钥解密后：" + str);





//        String text2 = "RAS测试、私钥加密 公钥解密";
//
//
//        // 公钥加密
//        byte[] encrypt1 = rsa.encrypt(StrUtil.bytes(text2, CharsetUtil.UTF_8), KeyType.PrivateKey);
//
//        // 私钥解密
//        byte[] decrypt2 = rsa.decrypt(encrypt1, KeyType.PublicKey);
//
//        String str2 = new String(decrypt2, "UTF-8");
//
//        System.out.println("私钥加密 公钥解密后：" + str2);

//        BASE64Decoder decoder = new BASE64Decoder();
//
//        //已知私钥及密文如何加解密
//        String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA"
//                + "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"
//                + "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta"
//                + "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"
//                + "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP"
//                + "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"
//                + "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"
//                + "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"
//                + "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"
//                + "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";
//
//        RSA rs2 = new RSA(PRIVATE_KEY, null);
//        String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F"+
//                "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"+
//                "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";
//        byte[] aByte = HexUtil.decodeHex(a);
//        byte[] decrypt3 = rs2.decrypt(aByte,KeyType.PrivateKey);
//        String txt = new String(decrypt3);
//        System.out.println("解密后的文本信息：" + txt);    //虎头闯杭州,多抬头看天,切勿只管种地



//
//        RSA rsa = SecureUtil.rsa();
//        System.out.println(rsa.getPublicKeyBase64());
//
//        System.out.println("=================================================================");
//
//        System.out.println(rsa.getPrivateKeyBase64());

        // 使用RSA算法生成密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();

        PublicKey publicKey = keyPair.getPublic();

        // 输出私钥
        System.out.println("RSA Public Key: " + Base64.encode(publicKey.getEncoded()));

        // 输出私钥
        System.out.println("RSA Private Key: " + Base64.encode(privateKey.getEncoded()));


    }

}
